/*
  Copyright (c) 2014 Dimitrij Gester

  "Smart RC TX" is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  "Smart RC TX" is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with "Smart RC TX"; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA
*/

package com.codeplex.smartrctx.configurator.communication;

import java.io.IOException;
import java.net.SocketException;
import java.util.List;

import com.codeplex.smartrctx.configurator.communication.CommLink.DataReceivedHandler;

import android.util.Log;

public class Transceiver implements DataReceivedHandler {
	public interface ProgressReceiver {
		public void setProgress(float progress);
	}

	private static final int MAX_TX_RETRIES = 32;
	private static final int ACKNOWLEDGE_GRACE_TIME = 20;
	private CommLink commLink;
	private ProgressReceiver progressReceiver;

	long txPause;
	private volatile boolean acknowledged;

	public Transceiver(CommLink commLink, long txDelay) {
		if (commLink == null)
			throw new NullPointerException("communicator must not be null");

		if (txDelay < 0)
			throw new IllegalArgumentException(
					"transmit pause must be positive");

		this.txPause = txDelay;
		this.commLink = commLink;
		this.commLink.addOnReceiveHandler(this);
	}

	public void setProgressReceiver(ProgressReceiver r) {
		this.progressReceiver = r;
	}

	public void sendCommands(List<List<Byte>> commands, boolean withConfirmation) {

		try {
			float max = commands.size();
			int i = 0;
			for (List<Byte> cmds : commands) {
				if (progressReceiver != null) {
					progressReceiver.setProgress(++i / max);
				}

				try {
					int repetitions = 0;
					acknowledged = !withConfirmation;
					do {
						if (repetitions == MAX_TX_RETRIES) {
							throw new IOException(
									"repeated transmission error.");
						}
						repetitions++;
						// transmit one configuration word..
						for (Byte b : cmds) {
							this.commLink.send(b);
//							try {
//								Thread.sleep(txPause);
//							} catch (InterruptedException e) {
//							}
						}

//						Log.i("TRANSMITTER", "word [" + i + "/" + commands.size() + "] r" + repetitions, null);
						try {
							Thread.sleep(ACKNOWLEDGE_GRACE_TIME);
						} catch (InterruptedException e) {
						}

						// ..and wait for an ack.
					} while (!acknowledged);
				} catch (SocketException e) {
					this.commLink.disconnect();
					this.commLink.connect();
					Log.w("BT Connection",
							"could not send configuration, reconnecting", e);
				}

			}
		} catch (IOException e) {
			Log.w("BT Connection", "could not send configuration", e);
		} catch (Throwable e) {
			Log.w("BT Connection", "unknown error", e);
		}
	}

	@Override
	public void dataReceived(String data) {
		/*
		 * this method is called from a background thread, so no UI objects may
		 * be interfaced here.
		 */

		// Log.i("COMM_REC", data);
		
		if(data.equals("ACK") || data.equals("ERR")) {
			Log.i("Received_Response", data, null);
		}
		
		if (data.equals("ACK"))
			acknowledged = true;

	}
}